/*
	Safe Proxy
*/

#include <stdio.h>
#include <sys/types.h>
#include <pwd.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <event.h>

#include "safeproxy.h"
#include "PidFile.h"
#include "Config.h"
#include "Server.h"


static void usage(void) {
	printf("Safeproxy - usage.\n\n");
}


static void sig_handler(const int sig) {
    printf("SIGINT handled.\n");
    exit(0);
}





int main (int argc, char **argv) {
    
	int c;
	bool daemonize=0;
	char *username=NULL;
	char *pid_file=NULL;
	int lport=DEFAULT_LISTEN_PORT;
	int maxconns=DEFAULT_MAX_CONNS;
	
	struct passwd *pw;
	PidFile pidfile;
	Config config;
	Server server;
    
	/* handle SIGINT */
	signal(SIGINT, sig_handler);

	/* process arguments */
	while ((c = getopt(argc, argv, "hdp:c:u:P:")) != -1) {
		switch (c) {
			case 'h':
				usage();
				exit(EXIT_SUCCESS);
				break;
			
			case 'd':
				daemonize = true;
				break;
				
			case 'p':
				lport = atoi(optarg);
				break;
			
			case 'c':
				maxconns = atoi(optarg);
				break;
			
			case 'u':
				username = optarg;
				break;

			case 'P':
				pid_file = optarg;
				break;
        
			default:
				fprintf(stderr, "Illegal argument \"%c\"\n", c);
				return 1;
		}
	}



	/* lose root privileges if we have them */
	if (getuid() == 0 || geteuid() == 0) {
		if (username == 0 || *username == '\0') {
			fprintf(stderr, "can't run as root without the -u switch\n");
			return 1;
		}
		if ((pw = getpwnam(username)) == 0) {
			fprintf(stderr, "can't find the user %s to switch to\n", username);
			return 1;
		}
		if (setgid(pw->pw_gid) < 0 || setuid(pw->pw_uid) < 0) {
			fprintf(stderr, "failed to assume identity of user %s\n", username);
			return 1;
		}
	}

	/* daemonize if requested */
	/* if we want to ensure our ability to dump core, don't chdir to / */
	if (daemonize) {
		if (daemon(0, 0) == -1) {
			fprintf(stderr, "failed to daemon() in order to daemonize\n");
			return 1;
		}
	}
	
	/* initialize main thread libevent instance */
	event_init();
	
	if (daemonize) {
		if (pid_file != NULL) {
			pidfile.Create(getpid(), pid_file);
		}
	}
    
  ASSERT(lport > 0);
	if (server.Listen(lport) == false) {
		fprintf(stderr, "failed to listen on port %d\n", lport);
 		exit(EXIT_FAILURE);
	}
	else {
		fprintf(stderr, "Listening on port %d\n", lport);
	}

	if (event_dispatch() != 0) {
		fprintf(stderr, "dispatch failed.\n");
	}

	printf("Goodbye.\n\n");  
	return 0;
}
